package tech.xs.sys.controller;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import tech.xs.common.framework.domain.annotations.AuthApi;
import tech.xs.common.framework.domain.entity.BaseEntity;
import tech.xs.common.framework.domain.enums.DataSourceTypeEnum;
import tech.xs.common.framework.domain.model.ApiResult;
import tech.xs.common.framework.domain.model.PageResult;
import tech.xs.common.framework.util.DictUtil;
import tech.xs.common.sys.domain.constant.PermissionConstant;
import tech.xs.sys.domain.bo.dict.ManualEditDictDataBo;
import tech.xs.sys.domain.bo.dict.QueryDictDataBo;
import tech.xs.sys.domain.entity.SysChildDictData;
import tech.xs.sys.domain.entity.SysDict;
import tech.xs.sys.domain.entity.SysDictData;
import tech.xs.sys.service.SysChildDictDataService;
import tech.xs.sys.service.SysDictDataService;
import tech.xs.sys.service.SysDictService;

import javax.annotation.Resource;
import java.util.List;

/**
 * 字典数据管理
 *
 * @author 沈家文
 * @since 2023/5/15 17:34
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/dict/data")
public class SysDictDataController {

    @Resource
    private SysDictDataService sysDictDataService;
    @Resource
    private SysDictService sysDictService;
    @Resource
    private SysChildDictDataService sysChildDictDataService;

    /**
     * 分页查询字典数据
     *
     * @param bo 请求数据
     * @return 响应数据
     * @author 沈家文
     * @since 2023/5/15 17:35
     */
    @GetMapping("/list/page")
    @AuthApi(permissions = PermissionConstant.DICT_MGR)
    public PageResult<SysDictData> listPage(@ModelAttribute QueryDictDataBo bo) {
        return PageResult.success(sysDictDataService.selectJoinListPage(bo.page(), SysDictData.class, bo.query()));
    }

    /**
     * 查询全量字典数据
     *
     * @param bo 请求参数
     * @return 响应数据
     * @author 沈家文
     * @since 2023/5/26 16:58
     */
    @GetMapping("/list/all")
    @AuthApi(permissions = PermissionConstant.DICT_MGR)
    public ApiResult<List<SysDictData>> listAll(@ModelAttribute QueryDictDataBo bo) {
        return ApiResult.success(sysDictDataService.selectJoinList(SysDictData.class, bo.query()));
    }

    /**
     * 新增或更新字典数据
     *
     * @param bo 请求参数
     * @return 响应数据
     * @author 沈家文
     * @since 2023/5/15 17:35
     */
    @PostMapping("/saveOrUpdate/manual")
    @AuthApi(permissions = PermissionConstant.DICT_MGR)
    public ApiResult<SysDictData> manualEdit(@Validated @RequestBody ManualEditDictDataBo bo) {
        bo.checkParameter();
        
        SysDict dict = sysDictService.getOne(Wrappers.<SysDict>lambdaQuery().eq(SysDict::getCode, bo.getDictCode()));
        if (dict == null) {
            return ApiResult.error("字典不存在 dictCode:" + bo.getDictCode());
        }

        long existCount = sysDictDataService.count(Wrappers.<SysDictData>lambdaQuery()
                .eq(SysDictData::getCode, bo.getCode())
                .eq(SysDictData::getDictId, dict.getId())
                .ne(bo.getId() != null, BaseEntity::getId, bo.getId()));
        if (existCount > 0) {
            return ApiResult.error("数据编码已经存在 dictCode:" + bo.getDictCode() + " 数据编码:" + bo.getCode());
        }

        SysDictData saveData = new SysDictData();
        BeanUtil.copyProperties(bo, saveData);
        if (bo.getId() != null) {
            SysDictData dbData = sysDictDataService.getOne(Wrappers.<SysDictData>lambdaQuery().eq(BaseEntity::getId, bo.getId()));
            if (dbData == null) {
                return ApiResult.error("根据id在系统中未查询到数据");
            }
            if (DataSourceTypeEnum.SystemGeneration.equals(dbData.getSource())) {
                return ApiResult.error("系统生成字典数据禁止修改");
            }
            if (!dbData.getDictId().equals(dict.getId())) {
                return ApiResult.error("不允许修改字典数据绑定的字典");
            }
        }
        try {
            DictUtil.getCodeValue(dict.getValueType(), saveData.getCode());
        } catch (Exception e) {
            log.error("code与字典数据类型不匹配", e);
            return ApiResult.error("code与字典数据类型不匹配 valueType:" + dict.getValueType() + " code:" + saveData.getCode());
        }
        saveData.setSource(DataSourceTypeEnum.Manual);
        saveData.setDictId(dict.getId());
        log.info("手动更新或保存字典数据:" + saveData);
        sysDictDataService.saveOrUpdate(saveData);
        sysDictService.reloadDictCache(dict.getCode());
        return ApiResult.success(saveData);
    }

    /**
     * 根据id删除字典数据
     * <p>
     * 1.子字典数据也会被删除<br>
     * 2.重新加载字典缓存和子字典缓存
     *
     * @param id id
     * @return 响应数据
     * @author 沈家文
     * @since 2023/5/17 14:51
     */
    @DeleteMapping("/delete/id")
    @AuthApi(permissions = PermissionConstant.DICT_MGR)
    public ApiResult deleteByCode(@RequestParam Long id) {
        if (id == null) {
            return ApiResult.error("id不能为空");
        }
        SysDictData dictData = sysDictDataService.getOne(Wrappers.<SysDictData>lambdaQuery().eq(SysDictData::getId, id));
        if (dictData == null) {
            return ApiResult.error("字典数据不存在或已删除 id" + id);
        }
        SysDict dict = sysDictService.getById(dictData.getDictId());
        log.info("删除字典数据:" + dictData);
        sysDictDataService.removeById(id);
        sysChildDictDataService.remove(Wrappers.<SysChildDictData>lambdaQuery().eq(SysChildDictData::getDictDataId, dictData.getId()));
        sysDictService.reloadDictCache(dict.getCode());
        return ApiResult.success();
    }

}
